import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 论文数据提取工具类，从docx文件中提取指定字段并封装为PaperData对象
 */
public class PaperDataExtractor {
    private static final Logger logger = LoggerFactory.getLogger(PaperDataExtractor.class);
    // 文档路径（需替换为你的6969-onlinefirst-Revised-Manuscript.docx实际路径）
    private static final String DOCX_PATH = "6969-onlinefirst-Revised-Manuscript.docx";
    public static void main(String[] args) {
        try {
            // 调试：先打印文档结构
            System.out.println("=== 开始调试文档结构 ===");
            XWPFDocument doc = new XWPFDocument(new FileInputStream(DOCX_PATH));
            int index = 0;
            for (XWPFParagraph para : doc.getParagraphs()) {
                String text = para.getText().trim();
                if (!text.isEmpty()) {
                    System.out.println("[" + index + "] " + text);
                    index++;
                }
            }
            doc.close();
            System.out.println("=== 结束调试 ===");

            // 然后运行提取
            PaperData paperData = extractPaperData(DOCX_PATH);
            System.out.println("论文数据提取结果：\n" + paperData);

        } catch (IOException e) {
            logger.error("读取docx文件失败：", e);
        } catch (Exception e) {
            logger.error("数据提取过程异常：", e);
        }
    }

    /**
     * 核心方法：从指定docx文件中提取论文数据
     * @param docxPath docx文件路径
     * @return 封装好的PaperData对象
     * @throws IOException 文档读取异常
     */
    /**
     * 核心方法：从指定docx文件中提取论文数据
     */
    public static PaperData extractPaperData(String docxPath) throws IOException {
        PaperData paperData = new PaperData();
        XWPFDocument document = null;
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(docxPath);
            document = new XWPFDocument(fis);
            List<XWPFParagraph> paragraphs = document.getParagraphs();

            // 标识变量
            //当程序检测到 “References” 关键词时，会将其设为true。开始读取引用内容
            boolean isExtractingReferences = false;
            //
            StringBuilder referencesBuilder = new StringBuilder();

            // 用于存储作者单位信息的列表
            List<String> authorAffiliations = new ArrayList<>();

            // 标志变量，用于标识是否已找到DOI，正在查找作者信息
            boolean isAfterDOI = false;
            boolean isBeforeCorrespondingAuthor = true;

            // 遍历所有段落，提取对应字段
            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph para = paragraphs.get(i);
                String paraText = para.getText().trim();
                if (paraText.isEmpty()) {
                    continue;
                }

                // 1. 提取日期字段
                if (paraText.startsWith("Received:")) {
                    extractDates(paraText, paperData);
                }

                // 2. 提取DOI
                else if (paraText.startsWith("DOI:")) {
                    String doi = paraText.replace("DOI:", "").trim();
                    paperData.setDoi(doi);
                    isAfterDOI = true; // 标记已经过了DOI行
                }

                // 3. 提取标题 - 修复：直接匹配标题文本
                else if (paraText.equals("Predicting and Reducing Wireless Customer Churn Using the AI2-Sriya Expert Index (SXI)")) {
                    paperData.setTitle(paraText);
                }
                // 4. 提取期刊名
                else if (paraText.equals("Journal of Data Science and Intelligent Systems")) {
                    paperData.setJournalName(paraText);
                    // 下一个段落是页码
                    if (i + 1 < paragraphs.size()) {
                        String pageInfo = paragraphs.get(i + 1).getText().trim();
                        if (pageInfo.startsWith("yyyy, Vol. XX(XX) 1–5")) {
                            String chinesePageInfo = pageInfo + "；" +
                                    pageInfo.replace("yyyy", "yyyy年")
                                            .replace("Vol. ", "第")
                                            .replace("(", "卷（第")
                                            .replace(")", "期）")
                                            .replace(" 1–5", "，第1-5页");
                            paperData.setPageInfo(chinesePageInfo);
                        }
                    }
                }

                // 5. 提取作者列表 - 使用锚点+内容特征定位：在DOI之后，通讯作者之前
                else if (isAfterDOI && isBeforeCorrespondingAuthor && containsAuthorPattern(paraText)) {
                    //提取作者名字那一整行
                    paperData.setAuthorRawText(paraText);
                    //每个作者名字创建一个Author对象，存入authors

                    //处理文本：清除*号、替换and为逗号（统一分隔符）
                    String processedText = paraText.replaceAll("[*]", "").replaceAll("\\s+and\\s+", ", ");

                    // 按逗号分割，遍历每个片段提取作者名（清除数字和空格）
                    List<Author> authors = new ArrayList<>();
                    String[] parts = processedText.split(",");
                    for (String part : parts) {
                        // 清除片段中的数字和前后空格
                        String name = part.replaceAll("\\d+", "").trim();
                        // 过滤空字符串（避免因连续分隔符产生的空值）
                        if (!name.isEmpty()) {
                            Author author = new Author();
                            author.setName(name);
                            authors.add(author);
                        }
                    }

                    // 保存处理后的作者列表
                    paperData.setAuthors(authors);

                    // 读取接下来的作者单位段落（根据数字序号匹配）
                    authorAffiliations.clear();
                    // 查找作者信息（包含作者详细信息的段落）
                    for (int j = 1; j <= authors.size(); j++) {
                        if (i + j < paragraphs.size()) {
                            String affiliationText = paragraphs.get(i + j).getText().trim();
                            // 匹配以数字开头的行（作者单位信息）
                            if (affiliationText.matches("^\\d+\\s+.*")) {
                                // 不处理中文翻译
                                authorAffiliations.add(affiliationText);
                            }
                            // 如果遇到通讯作者或其他非单位信息，则停止
                            else if (affiliationText.startsWith("*Corresponding author:") ||
                                    affiliationText.startsWith("Abstract:") ||
                                    affiliationText.startsWith("Keywords:")) {
                                break;
                            }
                        }
                    }

                    // 为作者设置详细信息（职位、公司、国籍）
                    if (!authors.isEmpty() && !authorAffiliations.isEmpty()) {
                        for (int k = 0; k < Math.min(authors.size(), authorAffiliations.size()); k++) {
                            Author author = authors.get(k);
                            String affiliation = authorAffiliations.get(k);
                            // 解析作者详细信息：1 Data Scientist, Sriya.AI LLC, USA
                            String[] parts1 = affiliation.split(",");
                            if (parts1.length >= 1) {
                                // 提取职位（去掉前面的数字）
                                String position = parts1[0].replaceAll("^\\d+\\s*", "").trim();
                                author.setPosition(position);
                            }
                            if (parts1.length >= 2) {
                                author.setCompany(parts1[1].trim());
                            }
                            if (parts1.length >= 3) {
                                author.setNationality(parts1[2].trim());
                            }
                        }
                    }

                    paperData.setAuthorAffiliations(authorAffiliations);
                }

                // 6. 提取通讯作者 - 精确解析
                else if (paraText.contains("Corresponding author:") || paraText.contains("*Corresponding author:")) {
                    isBeforeCorrespondingAuthor = false;

                    // 保存通讯作者原始文本
                    paperData.setCorrespondingAuthorRawText(paraText);

                    // 创建通讯作者对象
                    CorrespondingAuthor correspondingAuthor = new CorrespondingAuthor();

                    System.out.println("=== 开始提取通讯作者 ===");
                    System.out.println("原始通讯作者段落: " + paraText);

                    // 精确解析通讯作者信息
                    String cleanText = paraText;

                    // 移除标记文本
                    if (cleanText.contains("*Corresponding author:")) {
                        cleanText = cleanText.replace("*Corresponding author:", "").trim();
                    } else if (cleanText.contains("Corresponding author:")) {
                        cleanText = cleanText.replace("Corresponding author:", "").trim();
                    }

                    System.out.println("清理后文本: " + cleanText);

                    // 改进的解析方法：先提取邮箱，然后解析剩余部分
                    Pattern emailPattern = Pattern.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
                    Matcher emailMatcher = emailPattern.matcher(cleanText);

                    // 提取邮箱
                    if (emailMatcher.find()) {
                        String email = emailMatcher.group();
                        correspondingAuthor.setEmail(email);
                        System.out.println("提取邮箱: " + email);

                        // 移除邮箱部分
                        String infoWithoutEmail = cleanText.replace(email, "").replace("Email:", "").trim();
                        // 移除末尾的句号
                        infoWithoutEmail = infoWithoutEmail.replaceAll("\\.$", "").trim();
                        System.out.println("移除邮箱后文本: " + infoWithoutEmail);

                        // 按逗号分割剩余信息
                        String[] infoParts = infoWithoutEmail.split(",");
                        System.out.println("信息部分分割数量: " + infoParts.length);
                        for (int p = 0; p < infoParts.length; p++) {
                            System.out.println("部分[" + p + "]: '" + infoParts[p].trim() + "'");
                        }

                        // 解析各部分
                        if (infoParts.length >= 1) {
                            correspondingAuthor.setName(infoParts[0].trim());
                            System.out.println("提取姓名: " + infoParts[0].trim());
                        }
                        if (infoParts.length >= 2) {
                            correspondingAuthor.setPosition(infoParts[1].trim());
                            System.out.println("提取职位: " + infoParts[1].trim());
                        }
                        if (infoParts.length >= 3) {
                            correspondingAuthor.setCompany(infoParts[2].trim());
                            System.out.println("提取公司: " + infoParts[2].trim());
                        }
                        if (infoParts.length >= 4) {
                            correspondingAuthor.setNationality(infoParts[3].trim());
                            System.out.println("提取国籍: " + infoParts[3].trim());
                        }
                    }



                    // 调试输出每个字段的提取结果
                    System.out.println("提取结果检查:");
                    System.out.println("  Name: " + correspondingAuthor.getName());
                    System.out.println("  Position: " + correspondingAuthor.getPosition());
                    System.out.println("  Company: " + correspondingAuthor.getCompany());
                    System.out.println("  Nationality: " + correspondingAuthor.getNationality());
                    System.out.println("  Email: " + correspondingAuthor.getEmail());

                    paperData.setCorrespondingAuthor(correspondingAuthor);
                    System.out.println("最终通讯作者: " + correspondingAuthor);
                    System.out.println("=== 结束提取通讯作者 ===\n");
                }
                // 7. 提取摘要 - 修复：Abstract后面是冒号不是**号
                else if (paraText.startsWith("Abstract:")) {
                    String abstractContent = paraText.replace("Abstract:", "").trim();
                    paperData.setAbstractContent(abstractContent);
                }

                // 8. 提取关键词 - 修复：Keywords后面是冒号不是**号
                else if (paraText.startsWith("Keywords:")) {
                    String keywordsStr = paraText.replace("Keywords:", "").trim();
                    List<String> keywords = new ArrayList<>();
                    for (String keyword : keywordsStr.split(",")) {
                        keywords.add(keyword.trim());
                    }
                    paperData.setKeywords(keywords);
                }

                // 9. 提取引用
                else if (paraText.equals("References")) {
                    isExtractingReferences = true;
                    referencesBuilder.append(paraText).append("\n");
                }
                else if (isExtractingReferences) {
                    referencesBuilder.append(paraText).append("\n");
                }
            }

            paperData.setReferences(referencesBuilder.toString().trim());

        } finally {
            if (fis != null) fis.close();
            if (document != null) document.close();
        }

        return paperData;
    }

    /**
     * 检查段落是否包含作者信息的特征模式
     * @param text 段落文本
     * @return 是否包含作者信息
     */
    private static boolean containsAuthorPattern(String text) {
        // 包含数字和星号的模式，通常是作者行的特征
        return text.matches(".*[A-Z][a-z]+.*\\d+.*\\*.*") ||
                text.matches(".*,\\s*\\d+\\s*,\\s*\\*.*") ||
                text.matches(".*[A-Z][a-z]+\\s+[A-Z](\\s*[A-Z]*)?\\s*\\d+.*");
    }

    /**
     * 从文本中提取所有作者姓名
     * @param text 包含作者信息的文本
     * @return 作者姓名列表
     */
    private static List<String> extractAllAuthorNames(String text) {
        List<String> authorNames = new ArrayList<>();

        // 作者行示例："Nikhil K M1,*, Reeshabh Kumar2, Prashant Yadav3, Mahesh Banavar4 and Srinivas Kilambi5"
        // 先移除特殊符号
        String cleanText = text.replaceAll("[*]", "");

        // 使用正则表达式匹配所有作者姓名
        // 作者姓名格式：[FirstName] [MiddleInitial] [LastName][Number][,]
        // 处理"and"连接符
        cleanText = cleanText.replaceAll("\\s+and\\s+", ", ");
        System.out.println("清理后的作者文本: " + cleanText); // 调试信息

        // 使用更准确的正则表达式匹配所有作者姓名
        Pattern authorPattern = Pattern.compile("([A-Z][a-z]+\\s+[A-Z](?:\\s+[A-Za-z]+)?)\\s*\\d+");
        Matcher matcher = authorPattern.matcher(cleanText);

        while (matcher.find()) {
            String authorName = matcher.group(1).trim();
            if (!authorName.isEmpty()) {
                authorNames.add(authorName);
            }
        }

//         如果正则表达式没有匹配到足够的作者，使用备用方法
        if (authorNames.size() < 5) {
            authorNames.clear();
            // 按逗号分割
            String[] parts = cleanText.split(",");
            for (String part : parts) {
                // 匹配作者姓名格式：[FirstName] [MiddleInitial] [LastName]
                Pattern namePattern = Pattern.compile("([A-Z][a-z]+\\s+[A-Z](?:\\s+[A-Za-z]+)?)");
                Matcher nameMatcher = namePattern.matcher(part);
                if (nameMatcher.find()) {
                    String authorName = nameMatcher.group(1).trim();
                    if (!authorName.isEmpty()) {
                        authorNames.add(authorName);
                    }
                }
            }
        }

        return authorNames;
    }

    /**
     * 辅助方法：修复日期提取
     */
    private static void extractDates(String dateText, PaperData paperData) {
        // 文档中实际是 "|" 而不是 "|"
        String[] dateItems = dateText.split("\\|");
        for (String item : dateItems) {
            String itemTrimmed = item.trim();
            if (itemTrimmed.startsWith("Received:")) {
                paperData.setReceivedDate(itemTrimmed.replace("Received:", "").trim());
            } else if (itemTrimmed.startsWith("Revised:")) {
                paperData.setRevisedDate(itemTrimmed.replace("Revised:", "").trim());
            } else if (itemTrimmed.startsWith("Accepted:")) {
                paperData.setAcceptedDate(itemTrimmed.replace("Accepted:", "").trim());
            } else if (itemTrimmed.startsWith("Published online:")) {
                paperData.setPublishedDate(itemTrimmed.replace("Published online:", "").trim());
            }
        }
    }
}